// AuthenticationServer.h


#ifndef __MNAMESERVER_H
#define __MNAMESERVER_H

#include <fstream>
#include <iostream>
#include <map>
#include <sstream>

#include "TcpListener.h"
#include "Thread.h"
#include "SQLiteMap.h"
#include "../mDNSTypes.h"

using namespace std;

namespace PracticaCaso
{
	class AuthenticationServer;
	class mDNSObserver: public Thread {
		private:
			int fd4Receiving;
			bool keepRunning;
			struct sockaddr_in addr;
			void run();
			AuthenticationServer* client;

		public:
			mDNSObserver(AuthenticationServer* client);
			~mDNSObserver();
			void stop();
	};

	class mDNSQueryWrapper {
		private:
			int fd4Sending;
			struct sockaddr_in addr;
			AuthenticationServer* client;

		public:
			mDNSQueryWrapper(AuthenticationServer* client);
			~mDNSQueryWrapper();
			void send (string str);
	};

	class AuthenticationServer: public TcpListener {
		private:
			string domain, pendingQuery, pendingQueryCode, solvedQuery;
			int randSeed;
			int codProceso[100];
			int codProcesoIndex;
			SQLiteMap * sqliteMap;
			map<string, string> dns2IpPortValidMap;
			map<string, string> code2DnsMap;
			map<string, map<string,int> > code2IpPortMap;
			bool  satisfiedQuery;
			string stadistic(string code);
			void loadMappings(string mappinsFileName);
			string delegateExternalDnsServer(string serverDetails, string dnsName);
			string delegatemDNSCommunity(string dnsName);
			mDNSObserver* observer;
			mDNSQueryWrapper* queryWrapper;
			void waitValidates(string cmd, string payload, string code);	
			int decypherCode(string code);
		public:
			AuthenticationServer(int p, string m);
			AuthenticationServer(const AuthenticationServer&);
			AuthenticationServer & operator = (const AuthenticationServer &);
			~AuthenticationServer();
			string Validate(string payload,string code);
			void mdns_management(string cmd, string payload, string code); 
			void mdns_manage_response(string cmd, string payload, string code); 
			void mdns_manage_request(string cmd, string payload, string code); 
			friend ostream & operator << (ostream &os,AuthenticationServer &n);
	};

	class AuthenticationServerThread: public Thread {
		private:
			TcpClient* dnsClient;
			AuthenticationServer& dnsServer;
			void run();
		public:
			AuthenticationServerThread(TcpClient* c,AuthenticationServer& s): dnsClient(c), dnsServer(s) {}
			~AuthenticationServerThread();
	};
};
#endif
